package com.origin.netlibrary;


import java.math.BigInteger;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPublicKey;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

public class SSLSocketClient {

    static SSLSocketFactory sslSocketFactory;
    static X509TrustManager x509TrustManager;

    public static synchronized SSLSocketFactory getSSLSocketFactory() {
        if (sslSocketFactory == null) {
            sslSocketFactory = getSSLSocketFactorySyncInit();
        }
        return sslSocketFactory;
    }

    //获取X509TrustManager
    public static synchronized X509TrustManager getX509TrustManager() {

        if (x509TrustManager == null) {
            x509TrustManager = getX509TrustManagerSyncInit();
        }
        return x509TrustManager;
    }

    //获取这个SSLSocketFactory
    private static SSLSocketFactory getSSLSocketFactorySyncInit() {

        try {
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, getTrustManager(), new SecureRandom());
            return sslContext.getSocketFactory();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    private static TrustManager[] getTrustManager() {
        TrustManager[] trustAllCerts = new TrustManager[]{getX509TrustManager()};
        return trustAllCerts;
    }



    private static X509TrustManager getX509TrustManagerSyncInit() {
        X509TrustManager x509TrustManager = new X509TrustManager() {

//            public static final String PUB_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyoVVnu2kMLospDNVxUmUReN5MYc7FDIBkcfYr9zWJXL55LTaR3oHfYWPMg74MEBBg3IHt5JibetH66U/hsUKRjnzMsE/5xVtjt9yV9YCbVSYloB2BqJNsVxAYLSFMQiZzsuruiCoCiRrwi5S2Q4X7aV9cZy2sQiQBzGYfkwje8wB+L63BgKA9ERKo+FNSjOpER+b4WfDqL+7CPa/qDVIYj56QLIqyMMmf7zCZDlWOxz7vhdqE7eqtirRbrefrIY+IiDVELhU7vuyazDeW84Gi4WJDy3PmgHSF4sMG11V7ovu7tcul51LSiUFPddVf18n+Bs0Bfl8Y0Z39K2nJ/PiDwIDAQAB";
            public static final String PUB_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqdkDIqINeELKh65sXoZwNv+ygIZ0yBA0sk4hYPt3zPsAKbagwLy1YeIM2f7RXPZIpgIUbCamcauyEEV+dtgMygzruoq5NP4DpF3upJnhxBfaDeuoFp1qMlhAH5+46uZ7WsmertyBKdpoK9BL++S0EdGDf5cD3ruqV8HT7p0f9GVEQHGdcDbyAcHMWh384K3/FvxM2vp2G3lF7wnEP2gRuGYnhOiKghESm/kPX2b9h+3wwcqRC07sYUXaMoO+s9ooU9SGTLFFU6/kO+qYjMz9eAHKt95j+RI7yoQ0CfkMTQRUPFvd2cRQjGEIfNROjpIioLk2HgK0p8vXy8MGL7OTLQIDAQAB";
//            public static final String PUB_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvSg9yNmeTnzMON+GPL+s9Rqv7NcqgCFWNhNdGWB71CNy64AiFiBWYrhg1Xzi/bK35kWH0V4FZWmGEEmDc/yGsmOrWbPsSU5iZPjGnJEu35WutT7WaGkIaatoZlcpv5J5I+nPqkKqbVMXvUtEig1srIons0shw71oNzyo8Xda2f0Jk/EJbJ1e0irSxrmZEBjWJjpTL+FpIHTgfU8nr/q7AyEBrEYIqBu20g/A69lGVJ8qi8B9sWAT/ac2SfabAkU82UsZWbPU74xuBb7kDGCGv7Z1PfNHSskxWtx5Subb30YSjqJDVsdOy9UQEKjTVIBLjxozmbbg2CuQaH8dTHRisQIDAQAB";

            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType) {
            }

            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {

                if (chain == null) {
                    throw new IllegalArgumentException("checkServerTrusted:x509Certificate array isnull");
                }

                if (!(chain.length > 0)) {
                    throw new IllegalArgumentException("checkServerTrusted: X509Certificate is empty");
                }

                if (!(null != authType && authType.equalsIgnoreCase("RSA"))) {
                    throw new CertificateException("checkServerTrusted: AuthType is not RSA");
                }

                // Perform customary SSL/TLS checks
                try {
                    TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
                    tmf.init((KeyStore) null);
                    for (TrustManager trustManager : tmf.getTrustManagers()) {
                        ((X509TrustManager) trustManager).checkServerTrusted(chain, authType);
                    }
                } catch (Exception e) {
                    throw new CertificateException(e);
                }
                // Hack ahead: BigInteger and toString(). We know a DER encoded Public Key begins
                // with 0×30 (ASN.1 SEQUENCE and CONSTRUCTED), so there is no leading 0×00 to drop.
                RSAPublicKey pubkey = (RSAPublicKey) chain[0].getPublicKey();

                String encoded = new BigInteger(1 /* positive */, pubkey.getEncoded()).toString(16);
                // Pin it!
                final boolean expected = PUB_KEY.equalsIgnoreCase(encoded);

                if (!expected) {
                    throw new CertificateException("checkServerTrusted: Expected public key: "
                            + PUB_KEY + ", got public key:" + encoded);
                }

            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }
        };
        return x509TrustManager;
    }


    //获取HostnameVerifier
    public static HostnameVerifier getHostnameVerifier() {
        HostnameVerifier hostnameVerifier = new HostnameVerifier() {
            @Override
            public boolean verify(String s, SSLSession sslSession) {
                return true;
            }
        };
        return hostnameVerifier;
    }

}
